package client;

import java.io.IOException;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;

import javax.swing.JOptionPane;

import utils.ConnectionList;
import utils.IConnection;
import utils.Settings;
import utils.Table;

import commands.CommandJoinTableToOwner;

import enums.PlayerColor;

/**
 * Server for the game owner of a single RPS game. It communicates with the other player and viewers
 */
public class TableOwnerServerThread extends Thread
{
	private ConnectionThreadRPSClientToServer connRPSClientToServer = null; 
	private Table table = null;
	private String username = null;
	protected ConnectionList connections;
	private ServerSocket tableOwnerSocket = null;
	
	
	public TableOwnerServerThread(ConnectionThreadRPSClientToServer connRPSClientToServer, Table table, PlayerColor playerColor)
	{
		this.connRPSClientToServer = connRPSClientToServer;
		username = connRPSClientToServer.getUsername();
		connections = new ConnectionList();
		this.table = new Table(table);
	}
	
	public void run()
	{
		try {
			tableOwnerSocket = new ServerSocket (Settings.P2P_PORT);
			username = connRPSClientToServer.getUsername();
			
			// Open for the game owner, a connection thread from a game client to the game owner, from him to himself
			Socket socket = new Socket (Settings.P2P_HOST, Settings.P2P_PORT);
			ConnectionThreadTableClientToOwner conn = new ConnectionThreadTableClientToOwner (socket, getUsername(), connRPSClientToServer);
			conn.send(new CommandJoinTableToOwner(getUsername()));
			conn.start();
			
			while (true) {
				Socket clientSocket = tableOwnerSocket.accept ();
				ConnectionThreadTableOwnerToClient connectionThreadTableOwnerToClient = new ConnectionThreadTableOwnerToClient (clientSocket , this);
				connectionThreadTableOwnerToClient.start();
			}
		}
		catch (BindException bindEx) {
			String message = "You cannot create two tables on the same computer.";
			JOptionPane.showMessageDialog(connRPSClientToServer.getClientFrame(), message, "Cannot Create Table", JOptionPane.INFORMATION_MESSAGE);
		}
		catch (SocketException e) {
		}
		catch (Exception genEx) {
		    genEx.printStackTrace();
		}
		finally {
			try {
				if (tableOwnerSocket != null)
					tableOwnerSocket.close();
			}
			catch (IOException ioEx) {
			}
		}
	}
	
	public void removePlayer(String usernameToRemove)
	{
		getConnections().removeConnection(usernameToRemove);
		
		// Update the list of players for this table (Which is sent for future players to join this table)
		getTable().removePlayer(usernameToRemove);
		
		// If the last user left the table, close the socket that listens for socket openings
		if (getTable().getPlayerList().isEmpty())
		{
			try {
				tableOwnerSocket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	public ConnectionThreadRPSClientToServer getConnToMainServer(){
		return connRPSClientToServer;
	}
	public Table getTable(){
		return table;
	}
	public void setTable(Table table){
		this.table = table;
	}
	public String getUsername() {
	return username;
	}

	public ConnectionList getConnections() {
		return connections;
	}

	public void closeAllConnections()
	{
		for (IConnection currIConn : connections.getConnectionsList())
		{
			ConnectionThreadTableOwnerToClient currConn = (ConnectionThreadTableOwnerToClient)currIConn;
			
			try {
				// Stop the parsing loop in this connection thread
				currConn.stopLoop();
				
				// Close the socket to the game owner
				currConn.getSocket().close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		try {
			if (tableOwnerSocket != null)
				tableOwnerSocket.close();
		}
		catch (IOException ioEx) {
		}
	}
}
